OncePerRequestFilter是一個過濾器基類,確保過濾器邏輯只會在每個HTTP請求中執行一次,有助於確保正確行為並減少重複執行的風險。
繼承OncePerRequestFilter並實現doFilterInternal方法,在這個方法中編寫過濾器的具體邏輯,例如驗證或授權檢查。
這是一個簡單的範例,使用OncePerRequestFilter:
@Component
@RequiredArgsConstructor
@Slf4j
public class JwtAuthenticationFilter extends OncePerRequestFilter {
private final JwtService jwtService;
private final UserDetailsService userDetailsService;
@Override
protected void doFilterInternal(
@NonNull HttpServletRequest request,
@NonNull HttpServletResponse response,
@NonNull FilterChain filterChain
) throws ServletException, IOException {
final String authHeader = request.getHeader("Authorization");
final String jwt;
final String userEmail;
// 檢查是否有有效的 JWT 令牌
if (authHeader == null || !authHeader.startsWith("Bearer ")) {
filterChain.doFilter(request, response);
return;
}
jwt = authHeader.substring(7); // 提取JWT令牌
userEmail = jwtService.extractUsername(jwt); // 提取JWT中的使用者電子郵件
// 檢查當前的 Spring Security 上下文中是否存在身份驗證
if (userEmail != null && SecurityContextHolder.getContext().getAuthentication() == null) {
UserDetails userDetails = this.userDetailsService.loadUserByUsername(userEmail);
if (jwtService.validateToken(jwt, userDetails)) {
// 如果JWT令牌有效,設置身份驗證信息到Spring Security上下文
UsernamePasswordAuthenticationToken authToken = new UsernamePasswordAuthenticationToken(
userDetails,
null,
userDetails.getAuthorities()
);
authToken.setDetails(
new WebAuthenticationDetailsSource().buildDetails(request)
);
SecurityContextHolder.getContext().setAuthentication(authToken);
} else {
return;
}
}
// 繼續處理請求
filterChain.doFilter(request, response);
}
}
OncePerRequestFilter確保每個請求中的JWT令牌有效且未遭篡改,並將身份信息設置到Spring Security上下文中,實現身份認證和授權,確保只有合法的使用者能夠訪問特定的端點或資源。